//
//	File: RenderBatch.cpp
//

#include "RenderBatch.h"
#include "MaterialRenderer.h"
#include "AbstractMaterial.h"
#include "../OyDirect3D9.h"
#include "../OyDirect3D9_VertexCache.h"
#include "../OyDirect3D9_SkinManager.h"
#include "../Camera/D3D9Camera.h"

void CRenderBatch::PreRender()
{
	if( m_pSB )
	{
		m_pSB->MaterialModifier.m_material->PreRender(0);
	}
	else if( m_pVC )
	{
		m_pVC->m_MaterialModifier.m_material->PreRender(0);
	}
}

void CRenderBatch::PostRender()
{
	if( m_pSB )
	{
		m_pSB->MaterialModifier.m_material->PostRender(0);
	}
	else if( m_pVC )
	{
		m_pVC->m_MaterialModifier.m_material->PostRender(0);
	}
}

void CRenderBatch::Render()
{
	LPDIRECT3DDEVICE9 pDevice = GetMaterialRenderer()->GetD3DDevice();
	if( m_pSB )
	{
		D3DPRIMITIVETYPE PT = (D3DPRIMITIVETYPE)GetMaterialRenderer()->GetSkinManager()->GetSkin(m_pSB->nSkinID).nPrimitiveType;
		// Static Buffer ONLY Support TRIANGLELIST
		if( PT != D3DPT_TRIANGLELIST )
			return;

		pDevice->SetTransform( D3DTS_WORLD, (D3DMATRIX*)&m_MatWorld );
		pDevice->SetVertexDeclaration(m_pSB->pDecl);
		pDevice->SetStreamSource( 0, m_pSB->pVB, 0, m_pSB->nStride );	
		if( m_pSB->pIB )
		{
			pDevice->SetIndices( m_pSB->pIB );
			pDevice->DrawIndexedPrimitive( PT, 0, 0, m_pSB->nNumVerts, 0, m_pSB->nNumTris );
		}
		else
		{
			pDevice->DrawPrimitive( PT, 0, m_pSB->nNumTris );
		}
	}
	else if( m_pVC )
	{
		D3DPRIMITIVETYPE PT = (D3DPRIMITIVETYPE)GetMaterialRenderer()->GetSkinManager()->GetSkin(m_pVC->GetSkinID()).nPrimitiveType;

		pDevice->SetTransform( D3DTS_WORLD, (D3DMATRIX*)&m_MatWorld );

		pDevice->SetVertexDeclaration(m_pVC->m_pDecl);
		pDevice->SetStreamSource( 0, m_pVC->m_pVB, 0, m_pVC->m_nStride );	
		
		pDevice->SetIndices( m_pVC->m_pIB );

		switch( PT )
		{
			case D3DPT_TRIANGLELIST:
				pDevice->DrawIndexedPrimitive( PT, 0, 0, m_pVC->GetVertexNum(), 0, m_pVC->GetIndexNum()/3 );
				break;
			case D3DPT_LINELIST:
				pDevice->DrawIndexedPrimitive( D3DPT_LINELIST, 0, 0, m_pVC->GetVertexNum(),
					0, m_pVC->GetIndexNum()/2 );
				break;
			case D3DPT_LINESTRIP:
				pDevice->DrawIndexedPrimitive( D3DPT_LINESTRIP, 0, 0, m_pVC->GetVertexNum(),
                    0, m_pVC->GetVertexNum() );
				break;
			case D3DPT_POINTLIST:
				pDevice->DrawPrimitive( D3DPT_POINTLIST, 0, m_pVC->GetVertexNum() );
				break;

			default:
				break;
		}		
	}
}

// opaque
void COpaqueRenderBatch::BuildQueueValue()
{
	memset( &stQueueValue.ulQueueValue, 0x00, sizeof(ULONG64) );

	if( m_pSB )
	{
		stQueueValue.ulpriority = GetMaterialRenderer()->GetSkinManager()->GetSkin( m_pSB->nSkinID ).nTextureID[0];
	}
	else if( m_pVC )
	{
		stQueueValue.ulpriority = GetMaterialRenderer()->GetSkinManager()->GetSkin( m_pVC->GetSkinID() ).nTextureID[0];
	}
	else
		stQueueValue.ulpriority = 0;

	OyVector4D BoundingBOXCenter = m_BBOXCenter * m_MatWorld;
	OyVector4D dis = BoundingBOXCenter - OyVector4D(GetMaterialRenderer()->GetDirect3D9()->GetCurrentCamera()->GetPos());
	stQueueValue.uldistance = UINT32( dis.GetLength() );

	return;
}

// opaque with alphatest
void COpaqueAlphaTestRenderBatch::BuildQueueValue()
{
	memset( &stQueueValue.ulQueueValue, 0x00, sizeof(ULONG64) );

	if( m_pSB )
	{
		stQueueValue.ulpriority = GetMaterialRenderer()->GetSkinManager()->GetSkin( m_pSB->nSkinID ).nTextureID[0];
	}
	else if( m_pVC )
	{
		stQueueValue.ulpriority = GetMaterialRenderer()->GetSkinManager()->GetSkin( m_pVC->GetSkinID() ).nTextureID[0];
	}
	else
		stQueueValue.ulpriority = 0;

	OyVector4D BoundingBOXCenter = m_BBOXCenter * m_MatWorld;
	OyVector4D dis = BoundingBOXCenter - OyVector4D(GetMaterialRenderer()->GetDirect3D9()->GetCurrentCamera()->GetPos());
	stQueueValue.uldistance = UINT32( dis.GetLength() );

	return;
}

// Transparent
void CTransparentRenderBatch::BuildQueueValue()
{
	memset( &stQueueValue.ulQueueValue, 0x00, sizeof(ULONG64) );

	if( m_pSB )
	{
		stQueueValue.ulpriority = GetMaterialRenderer()->GetSkinManager()->GetSkin( m_pSB->nSkinID ).nTextureID[0];
	}
	else if( m_pVC )
	{
		stQueueValue.ulpriority = GetMaterialRenderer()->GetSkinManager()->GetSkin( m_pVC->GetSkinID() ).nTextureID[0];
	}
	else
		stQueueValue.ulpriority = 0;

	OyVector4D BoundingBOXCenter = m_BBOXCenter * m_MatWorld;
	OyVector4D dis = BoundingBOXCenter - OyVector4D(GetMaterialRenderer()->GetDirect3D9()->GetCurrentCamera()->GetPos());
	
	stQueueValue.uldistance = 0xFFFFFFFF - UINT32( dis.GetLength() );

	return;
}